<?php

declare(strict_types=1);

namespace App\Admin;

use App\Entity\AdminUser;
use App\Entity\AdminUserGroup;
use App\Form\Type\AdminUserAvatarFieldType;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Route\RouteCollection;
use Sonata\AdminBundle\Show\ShowMapper;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;

final class AdminUserAdmin extends AbstractAdmin {

    protected $baseRouteName = 'admin_admin_user';
    protected $baseRoutePattern = 'admin_user';
    protected $maxPageLinks = 10;
    private $passwordEncoder;

    public function __construct ($code, $class, $baseControllerName, UserPasswordEncoderInterface $passwordEncoder) {
        parent::__construct($code, $class, $baseControllerName);
        $this->passwordEncoder = $passwordEncoder;
    }

    public function toString ($object) {
        return $object instanceof AdminUser ? $object->getUsername() : '用户';
    }

    protected function configureDatagridFilters (DatagridMapper $datagridMapper): void {
        $datagridMapper
            ->add('username', null, ['label' => '用户名'])
            ->add('nickname', null, ['label' => '昵称'])
            ->add('email', null, ['label' => 'E-mail'])
            ->add('admin_user_group_id', 'doctrine_orm_choice', ['label' => '用户组'], ChoiceType::class, [
                'choices' => $this->getAdminUserGroupList(true),
            ]);
    }

    protected function configureListFields (ListMapper $listMapper): void {
        $listMapper
            ->addIdentifier('username', null, [
                'label'        => '用户名',
                'header_style' => 'width: 20%; text-align: left',
                'row_align'    => 'left',
            ])
            ->add('nickname', null, [
                'label'        => '昵称',
                'header_style' => 'width: 20%; text-align: left',
                'row_align'    => 'left',
            ])
            ->add('email', null, [
                'label'        => 'E-mail',
                'header_style' => 'width: 20%; text-align: left',
                'row_align'    => 'left',
            ])
            ->add('admin_user_group_id', 'string', [
                'label'        => '用户组',
                'header_style' => 'width: 15%; text-align: left',
                'row_align'    => 'left',
                'template'     => 'backend/admin_user/list_admin_user_group_id.html.twig',
            ])
            ->add('created_at', null, [
                'format'       => 'Y-m-d H:i:s',
                'timezone'     => 'PRC',
                'label'        => '创建时间',
                'header_style' => 'width: 15%; text-align: left',
                'row_align'    => 'left',
            ]);
    }

    protected function configureFormFields (FormMapper $formMapper): void {
        $password_help = $this->isCurrentRoute('create') ? '密码应包含数字和字母，长度6~20' : '留空则不更新密码，密码应包含数字和字母，长度6~20';
        $formMapper
            ->add('username', null, ['label' => '用户名'])
            ->add('nickname', null, ['label' => '昵称'])
            ->add('avatar', HiddenType::class)
            ->add('avatar_item', AdminUserAvatarFieldType::class, ['label' => '头像'])
            ->add('email', null, ['label' => 'E-mail'])
            ->add('password', RepeatedType::class, [
                'type'            => PasswordType::class,
                'invalid_message' => '密码不一致',
                'options'         => ['attr' => ['class' => 'password-field']],
                'required'        => $this->isCurrentRoute('create'),
                'first_options'   => ['label' => '密码', 'help' => $password_help],
                'second_options'  => ['label' => '确认密码'],
            ])
            ->add('admin_user_group_id', ChoiceType::class, [
                'label'   => '用户组',
                'choices' => $this->getAdminUserGroupList(true),
            ]);
    }

    private function getAdminUserGroupList ($is_turn = false) {
        $result = [];

        $admin_user_groups = $this->modelManager->findBy(AdminUserGroup::class);
        foreach ($admin_user_groups as $admin_user_group) {
            if ($is_turn) {
                $result[$admin_user_group->getName()] = $admin_user_group->getId();
            } else {
                $result[$admin_user_group->getId()] = $admin_user_group->getName();
            }
        }

        return $result;
    }

    protected function configureShowFields (ShowMapper $showMapper): void {
        $showMapper
            ->add('id')
            ->add('email')
            ->add('roles')
            ->add('password');
    }

    public function configureRoutes (RouteCollection $collection) {
        parent::configureRoutes($collection); // TODO: Change the autogenerated stub

        $collection->add('profile', 'profile');
        $collection->remove('show');
        $collection->remove('export');
    }

    public function preUpdate ($object) {
        parent::preUpdate($object); // TODO: Change the autogenerated stub

        if (!empty($object->getPassword())) {
            $new_password = $this->passwordEncoder->encodePassword($object, $object->getPassword());
            $object->setPassword($new_password);
        }
    }

    public function prePersist ($object) {
        parent::prePersist($object); // TODO: Change the autogenerated stub

        if (!empty($object->getPassword())) {
            $new_password = $this->passwordEncoder->encodePassword($object, $object->getPassword());
            $object->setPassword($new_password);
        }
    }

    public function getTemplate ($name) {
        switch ($name) {
            case 'edit':
                return 'backend/admin_user/edit.html.twig';
            default:
                return $this->getTemplateRegistry()->getTemplate($name);
        }
    }
}
